#include "mainwindow.h"
#include <QPainter>
#include <QMouseEvent>
#include <QPoint>
#include <QDebug>
#include <QDialog>
#include <QMessageBox>
#include <ctime>

void MainWindow::run_time(){
    if(cb_with_num.player == blackc) {
        black_timer->start();
        white_timer->pause();
    }
    else {
        white_timer->start();
        black_timer->pause();
    }
}

void MainWindow::wait_cal(){
    wait->show();
    during_cal = true;
    for(auto &i:btn_set) i->setDisabled(true);
    setnow->setEnabled(true);
    box->setDisabled(true);
}

void MainWindow::engine_notyify(Step s){
    setChess(s.oldchess,s.chess,s.hinder);
    wait->hide();
    during_cal = false;
    for(auto &i:btn_set) i->setEnabled(true);
    setnow->setDisabled(true);
    box->setEnabled(true);
    repaint();
    if(end_game()) return;
    else next();
}

void MainWindow::getpos(int x, int y, Chess &pos){
    pos.setxy((x - xdis)/wh+1,(y - ydis)/wh+1);
}
int MainWindow::rdiagonal(int x, int x0, int y0){
    return x + y0 -x0;
}
int MainWindow::ldiagonal(int x, int x0, int y0){
    return -x + x0 + y0;
}
bool MainWindow::isMoveChess(int x,int y,bool player) const{
    if(player){
        for (int i = 0;i < 4;i++) {
            if(cb_with_num.movechess.blackchess[i].x == x && cb_with_num.movechess.blackchess[i].y == y) return true;
        }
        return false;
    }
    else {
        for (int i = 0;i < 4;i++) {
            if(cb_with_num.movechess.whitechess[i].x == x && cb_with_num.movechess.whitechess[i].y == y) return true;
        }
        return false;
    }
}


void MainWindow::changeMoveChess(const Chess& last,const Chess& cur,bool player){
    if (player){
        for (int i =0;i < 4;i++)
            if(cb_with_num.movechess.blackchess[i] == last) {cb_with_num.movechess.blackchess[i] = cur;break;}
    }
    else for (int i=0;i < 4;i++)
        if(cb_with_num.movechess.whitechess[i] == last) {cb_with_num.movechess.whitechess[i] = cur;break;}
}

void MainWindow::mousePressEvent(QMouseEvent *e){
    if(isfin) return;
    if(during_cal) return;
    getpos(e->x(),e->y(),current.chess);
    if(current.time == 3) {
        current.time = 0;
        while (!undo_save.empty()) undo_save.pop();
    }
    if(current.time == 0)
    {
        if(cb_with_num.chessborad[current.chess.i] != cb_with_num.player || !isMoveChess(current.chess.x,current.chess.y,cb_with_num.player)) {
            goto end;
        }
        bool can_move = false;
        for (int i = 0 ;i < 8;i++ ) {
            if(cb_with_num.chessborad[current.chess.i + dection[i]] == 2){
                can_move = true;
                break;
            }
        }
        if(!can_move) goto end;
        while(!undo_save.empty()) undo_save.pop();
        cb_with_num.chessborad[current.chess.i] = 2;
        cur_s.oldchess = current.chess.i;
        current.lastchess = current.chess;
        if(cb_with_num.player)
        {
            cb_with_num.blackcurrentmove = current.lastchess.i;
            cb_with_num.blackcurrentset = 0;
            cb_with_num.blackcurrenthinder = 0;
            undo_save.push(cb_with_num.blackcurrentmove);
        }
        else{
            cb_with_num.whitecurrentmove = current.lastchess.i;
            cb_with_num.whitecurrentset = 0;
            cb_with_num.whitecurrenthinder = 0;
            undo_save.push(cb_with_num.whitecurrentmove);
        }
        current.time++;
    }
    else if(current.time == 1){
        if(!isLegal(current.lastchess,current.chess)) goto end;
        changeMoveChess(Chess(current.lastchess.x,current.lastchess.y),Chess(current.chess.x,current.chess.y),cb_with_num.player);
        current.lastchess = current.chess;
        cb_with_num.chessborad[current.chess.i] = cb_with_num.player;
        cur_s.chess = current.chess.i;
        if(cb_with_num.player)
        {
            cb_with_num.blackcurrentset = current.lastchess.i;
            undo_save.push(cb_with_num.blackcurrentset);
        }
        else{
            cb_with_num.whitecurrentset = current.lastchess.i;
            undo_save.push(cb_with_num.whitecurrentset);
        }
        current.time++;
    }
    else if (current.time == 2) {
        if(!isLegal(current.lastchess,current.chess)) goto end;
        cb_with_num.chess_num++;
        if(cb_with_num.player)
        {
            cb_with_num.blackcurrenthinder = current.chess.i;
            undo_save.push(cb_with_num.blackcurrenthinder);
        }
        else{
            cb_with_num.whitecurrenthinder = current.chess.i;
            undo_save.push(cb_with_num.whitecurrenthinder);
        }
        if(cb_with_num.player == blackc){
            cb_with_num.chessborad[current.chess.i] = blackh;
        }
        else {
            cb_with_num.chessborad[current.chess.i] = whiteh;
        }
        cur_s.hinder = current.chess.i;
        current.time++;
        step_save.push_back(cur_s);
        cb_with_num.player = !cb_with_num.player;
        update();
        if(end_game()) return;;
        next();
        goto end;
    }
    repaint();
    if(end_game()) return;
end:;
}

void MainWindow::paintEvent(QPaintEvent *e){
    QPainter pt(this);
    QFont font;
    font.setPointSize(15);
    pt.setFont(font);
    int i = 1, p = xdis + 15;
    for (;i <= 9;p += 50 ) {
        pt.drawText(p,20,QString(char('0'+ i++)));
    }
    pt.drawText(p,20,QString("10"));
    i = 1;p = ydis + 30;
    for (;i <= 9;p += 50 ) {
        pt.drawText(xdis - 20,p,QString(char('0'+ i++)));
    }
    pt.drawText(xdis - 35,p,QString("10"));
    for (int i=0;i <= 143;i++) {
        if(cb_with_num.chessborad[i] == blackc) pt.drawPixmap(xdis+(50-chessw)/2+50*(i%12-1),ydis+50*(i/12-1),chessw,chessh,*black);
        else if(cb_with_num.chessborad[i] == whitec)pt.drawPixmap(xdis+(50-chessw)/2+50*(i%12-1),ydis+50*(i/12-1),chessw,chessh,*white);
        else if(cb_with_num.chessborad[i] == blackh) pt.drawPixmap(xdis+ 2.5 +50*(i%12-1),ydis+2.5+50*(i/12-1),chessh-5,chessh-5,*blackhinder);
        else if (cb_with_num.chessborad[i] == whiteh) pt.drawPixmap(xdis+2.5+50*(i%12-1),ydis+2.5+50*(i/12-1),chessh-5,chessh-5,*whitehinder);
    }
    QPen pen(Qt::black);
    pen.setWidth(5);
    pt.setPen(pen);
    if(cb_with_num.blackcurrentmove != 0){
        pt.drawRect(xdis+50*(cb_with_num.blackcurrentmove%12-1),ydis+50*(cb_with_num.blackcurrentmove/12-1),50,50);
    }
    if(cb_with_num.blackcurrentset != 0){
        pt.drawRect(xdis+50*(cb_with_num.blackcurrentset%12-1),ydis+50*(cb_with_num.blackcurrentset/12-1),50,50);
    }
    if(cb_with_num.blackcurrenthinder != 0){
        pt.drawRect(xdis+50*(cb_with_num.blackcurrenthinder%12-1),ydis+50*(cb_with_num.blackcurrenthinder/12-1),50,50);
    }
    pen.setColor(Qt::white);
    pt.setPen(pen);
    if(cb_with_num.whitecurrentmove != 0){
        pt.drawRect(xdis+50*(cb_with_num.whitecurrentmove%12-1),ydis+50*(cb_with_num.whitecurrentmove/12-1),50,50);
    }
    if(cb_with_num.whitecurrentset != 0){
        pt.drawRect(xdis+50*(cb_with_num.whitecurrentset%12-1),ydis+50*(cb_with_num.whitecurrentset/12-1),50,50);
    }
    if(cb_with_num.whitecurrenthinder != 0){
        pt.drawRect(xdis+50*(cb_with_num.whitecurrenthinder%12-1),ydis+50*(cb_with_num.whitecurrenthinder/12-1),50,50);
    }
}

bool MainWindow::isLegal(const Chess& last, const Chess& cur){
    if(cb_with_num.chessborad[cur.i] != 2) return false;
    //在同一列上
    if(cur.x == last.x) {
        if(cur.y > last.y){
            for (int i = last.i+dection[4];i < cur.i;i+=dection[4])
                if(cb_with_num.chessborad[i] != 2) return false;
        }
        else if (cur.y < last.y) {
            for (int i = cur.i+dection[4];i < last.i;i+=dection[4])
                if(cb_with_num.chessborad[i] != 2) return false;
        }
        else return false;
        return true;
    }
    //在同一行上
    else if(cur.y == last.y) {
        if(cur.x > last.x){
            for (int i = last.i+1;i < cur.i;i++)
                if(cb_with_num.chessborad[i] != 2) return false;
        }
        else if (cur.x < last.x) {
            for (int i = cur.i+1;i < last.i;i++)
                if(cb_with_num.chessborad[i] != 2) return false;
        }
        else return false;
        return true;
    }

    //是否在一条直线上,此直线斜率为正负1，当k=1时，y=x+y0-x0;
    else if(cur.y == rdiagonal(cur.x,last.x,last.y)) {
        if(cur.x > last.x){
            for (int i = last.x+1;i < cur.x;i++)
                if(cb_with_num.chessborad[i+ 12 * rdiagonal(i,last.x,last.y)] != 2)
                    return false;
        }
        else if (cur.x < last.x) {
            for (int i = cur.x+1;i < last.x;i++)
                if(cb_with_num.chessborad[i + 12 * rdiagonal(i,last.x,last.y)] != 2)
                    return false;
        }
        return true;
    }
    else if(cur.y == (ldiagonal(cur.x,last.x,last.y))) {
        if(cur.x > last.x){

            for (int i = last.x+1;i < cur.x;i++){
                if(cb_with_num.chessborad[i + 12 * ldiagonal(i,last.x,last.y)] != 2)
                    return false;
            }
        }
        else if (cur.x < last.x) {
            for (int i = cur.x+1;i < last.x;i++){
                if(cb_with_num.chessborad[i + 12 *ldiagonal(i,last.x,last.y)] != 2)
                    return false;
            }
        }
        return true;
    }
    return false;
}

void MainWindow::firsthand()
{
    cb_with_num.player = 1;
    if(select == "随机先手"){
        srand(time(0));
        computer = rand()%2;
        if(computer == 1) {
            isfirst = true;
            emit computer_first();
        }
    }
    else if(select == "玩家先手"){
        computer = 0;
        isfirst = false;
        emit computer_remote();
    }
    else{
        computer = 1;
        isfirst = true;
        emit computer_first();
    }
    if(mode == computer_vs_human || mode == random){
        if(computer) fh->setText("电脑先执");
        else fh->setText("玩家先执");
    }
}

void MainWindow::setChess(const Chess& moch, const Chess& setch,const Chess& hinder){
    while (!undo_save.empty()) undo_save.pop();
    int movechess[2]{moch.x,moch.y};
    int setchess[2]{setch.x,setch.y};
    int hinderchess[2]{hinder.x,hinder.y};
    if(!isMoveChess(moch.x,moch.y,cb_with_num.player) || cb_with_num.chessborad[moch.i] != cb_with_num.player)
        return;
    if(!isLegal(movechess,setchess))
        return;
    cb_with_num.chessborad[moch.i] = 2;
    cb_with_num.chessborad[setch.i] = cb_with_num.player;
    changeMoveChess(moch,setch,cb_with_num.player);
    if(cb_with_num.player == blackc){
        cb_with_num.blackcurrentmove = moch.i;
        cb_with_num.blackcurrentset = setch.i;
        cb_with_num.blackcurrenthinder = hinder.i;
    }
    else{
        cb_with_num.whitecurrentmove = moch.i;
        cb_with_num.whitecurrentset = setch.i;
        cb_with_num.whitecurrenthinder = hinder.i;
    }
    update();
    if(!isLegal(setchess,hinderchess))
        return;
    if(cb_with_num.player == blackc){
        cb_with_num.chessborad[hinder.i] = blackh;
    }
    else {
        cb_with_num.chessborad[hinder.i] = whiteh;
    }
    cb_with_num.player = !cb_with_num.player;
    QString string = "所走棋子：" + QString::number(moch.x) + "," + QString::number(moch.y) + "  ";
    string += "移动位置：" +  QString::number(setch.x) + "," + QString::number(setch.y) + "  ";
    string += "障碍：" + QString::number(hinder.x) + "," + QString::number(hinder.y) + "  ";
    lastStep->setText(string);
    update();
    cb_with_num.chess_num++;
    step_save.push_back(Step(moch.i,setch.i,hinder.i));
}
